package com.dc.commons.views;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.springframework.util.Assert;
import org.springframework.web.servlet.ModelAndView;

import com.dc.commons.json.JsonWrapper;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.google.common.collect.Maps;

/**
 * *****************************************************************************
 * 文件名: ModelAndViewBuilder.java <br>
 * 版本: 1.0<br>
 * 描述: 视图创建辅助类， 辅助创建视图<br>
 * 版权所有: <br>
 * <P>
 * 创建者: 王建栋 <br>
 * 创建日期: 2015年12月16日 下午3:49:39<br>
 * 修改者: <br>
 * 修改日期: <br>
 * 修改说明: <br>
 *****************************************************************************
 */
public class ModelAndViewBuilder {

	/**
	 * 视图名称
	 */
	private String viewName;
	/**
	 * 业务对象
	 */
	private Object result;
	/**
	 * Json 结果键
	 */
	public static final  String resultKey=ModelAndViewBuilder.class.getName()+".RESULT";
	/**
	 * Json 对象包裹键
	 */
	public static final String jsonKey=ModelAndViewBuilder.class.getName()+".JSON_WRAPPER";
	/**
	 * 返回对象容器
	 */
	private Map<String,Object> map=new HashMap<String,Object>();
	/**
	 * Json 包装类
	 */
	private JsonWrapper jsonWrapper=null;
	
	/**
	 * Json 过滤器键值
	 */
	private String filterKey=FilterProvider.class.getName();
	/**
	 * Json 过滤器
	 */
	private Map<String,SimpleBeanPropertyFilter> filters=Maps.newHashMap();
	
	/**
	 * 创建 对象
	 * @return newBuilder 创建对象
	 */
	public static ModelAndViewBuilder create(){
		return new ModelAndViewBuilder();
	}
	
	/**
	 * 标记返回对象为成功
	 * @return builder对象 成功状态
	 */
	public ModelAndViewBuilder success(){
		this.jsonWrapper=JsonWrapper.success();
		return this;
	}
	
	/**
	 * 
	 * @param error 错误信息
	 * @return builder对象 失败状态，提供失败信息
	 */
	public ModelAndViewBuilder error(String error){
		this.jsonWrapper=JsonWrapper.error(error);
		return this;
	}
	
	/**
	 * 
	 * @param error 错误信息
	 * @param exception 异常对象
	 * @return builder对象 对象为失败，提供失败信息及异常
	 */
	public ModelAndViewBuilder error(String error,Throwable exception){
		this.jsonWrapper=JsonWrapper.error(error,exception);
		return this;
	}
	
	/**
	 * 直接设置 JsonWrapper
	 * @param jsonWrapper
	 * @return builder对象
	 */
	public ModelAndViewBuilder json(JsonWrapper jsonWrapper){
		this.jsonWrapper=jsonWrapper;
		return this;
	}
	
	/**
	 * 设置视图名称
	 * @param viewName 视图名称
	 * @return builder对象
	 */
	public ModelAndViewBuilder viewName(String viewName){
		this.viewName=viewName;
		return this;
	}
	
	/**
	 *  设置某一个类的 包含字段
	 * @param clazz 包含的类
	 * @param fields 包含的字段
	 * @return builder对象
	 */
	public ModelAndViewBuilder include(Class<? extends Serializable> clazz,String... fields){
		if(clazz.isAnnotationPresent(JsonFilter.class)){
			String filter=clazz.getAnnotation(JsonFilter.class).value();
			filters.put(filter, SimpleBeanPropertyFilter.filterOutAllExcept(fields));
		}
		return this;
	}
	
	/**
	 * 设置某一个类 不包含某字段
	 * @param clazz 不包含的类
	 * @param  fields 不包含的字段
	 * @return builder对象
	 */
	public ModelAndViewBuilder exclude(Class<? extends Serializable> clazz,String... fields){
		if(clazz.isAnnotationPresent(JsonFilter.class)){
			String filter=clazz.getAnnotation(JsonFilter.class).value();
			filters.put(filter, SimpleBeanPropertyFilter.serializeAllExcept(fields));
		}
		return this;
	}
	
	/**
	 *  设置返回结果对象
	 * @param result
	 * @return builder对象
	 */
	public ModelAndViewBuilder result(Object result){
		this.result=result;
		return this;
	}
	
	/**
	 *  提供额外的属性传递，以下两个键不可覆盖<br>
	 *  ModelAndViewBuilder.JSON_WRAPPER<br>
	 *  ModelAndViewBuilder.RESULT<br>
	 * @param key
	 * @param value
	 * @return	builder对象
	 */
	public ModelAndViewBuilder attribute(String key,Object value){
		Assert.isTrue(jsonKey.equals(key), jsonKey+", 有特殊的意义 不能覆盖！");
		Assert.isTrue(filterKey.equals(key),filterKey+", 具有特殊意义，不能覆盖！");
		map.put(key, value);
		return this;
	}
	
	/**
	 * 视图创建,视图名称，json包装对象，结果集 至少有一个
	 * @return builder对象
	 */
	public ModelAndView build(){
		if(viewName==null&&result==null&&jsonWrapper==null){
			throw new RuntimeException("参数有误， 视图，结果集，状态 至少需要传递一个");
		}
		ModelAndView view=new ModelAndView(viewName);
		if(result!=null){
			view.addObject(resultKey, result);
		}
		if(jsonWrapper!=null){
			view.addObject(jsonKey, jsonWrapper);
		}
		if(!filters.isEmpty()){
			SimpleFilterProvider defaultFilterProvider= new SimpleFilterProvider()
					.setDefaultFilter(SimpleBeanPropertyFilter.serializeAllExcept());
			for(String key:filters.keySet()){
				defaultFilterProvider.addFilter(key, filters.get(key));
			}
			view.addObject(filterKey, defaultFilterProvider);
		}
		
		if(!map.isEmpty()){
			view.addAllObjects(map);
		}
		return view;
	}
}
